package filter;

import com.alibaba.fastjson.JSONObject;

import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;

import javax.annotation.PostConstruct;

/**
 * @Author liuzesen
 * @CreateDate 16/3/24
 */
@Service
public class SensitiveWords {
    private HashMap<String, SensitiveWords> trie = new HashMap<>();
    private SensitiveWords parent = null;
    private SensitiveWords node = this;
    private SensitiveWords jump = null;
    private boolean isEnd = false;

    public void setJumpNode(HashMap<String, SensitiveWords> trie, SensitiveWords root) {
        for (String key : trie.keySet()) {
            // 父节点无跳转
            if (trie.get(key).parent.jump == null) {
                // 有相同后缀
                if (root.trie.get(key) != null) {
                    trie.get(key).jump = root.trie.get(key);
                } else {
                    trie.get(key).jump = null;
                }
            } else {
                // 有相同后缀，跳父节点跳转下一个
                if (root.trie.get(key) != null) {
                    trie.get(key).jump = trie.get(key).parent.jump.trie.get(key);
                } else {
                    // 没有相同后缀跳开头
                    trie.get(key).jump = null;
                }
            }

            // 继续下一层查找jump
            if (!trie.get(key).trie.keySet().isEmpty()) {
                setJumpNode(trie.get(key).trie, root);
            }
        }
    }

    public void flushJumpNode() {
        SensitiveWords root = this;

        for (String key : root.trie.keySet()) {
            root.trie.get(key).jump = null;
            setJumpNode(root.trie.get(key).trie, root);
        }
    }

    public void add(String word) {
        node = this;
        for (int index = 0; index < word.length(); index++) {
            // 没有这个字
            if (node.trie.get(String.valueOf(word.charAt(index))) == null) {
                node.trie.put(String.valueOf(word.charAt(index)), new SensitiveWords()); // 加上这个字
                parent = node;
                node = node.trie.get(String.valueOf(word.charAt(index)));
                node.parent = parent;
            } else {
                parent = node;
                node = node.trie.get(String.valueOf(word.charAt(index)));
                node.parent = parent;
            }

            // 是否是结尾
            if (index == word.length() - 1) {
                node.isEnd = true;
            }

        }
    }

    @PostConstruct
    public void update() {
        RestTemplate restTemplate = new RestTemplate();
        System.out.println("敏感词更新开始");
        JSONObject result = restTemplate.getForObject("http://st.api.yeshj.com/Plugin/GetOfficialBadWord", JSONObject.class);
        String[] sensitives = result.getString("data").split(",");
        for (String sensitive : sensitives) {
            add(sensitive);
        }
        flushJumpNode(); // 更新跳转树
        System.out.println("敏感词更新结束");
    }

    public boolean check(String article) {
        // 老版本检查，按位匹配
//        for (int index = 0; index < article.length(); index++) {
//            node = this;
//            int shift = 0;
//            while (((index + shift) < article.length()) && node.trie.get(String.valueOf(article.charAt(index + shift))) != null) {
//                node = node.trie.get(String.valueOf(article.charAt(index + shift)));
//                if (node.isEnd == true)
//                    return true;
//                shift++;
//            }
//        }
//        return false;

        SensitiveWords root = this;
        node = root;
        for (int index = 0; index < article.length(); index++) {
            // 该单词匹配
            if (node.trie.get(String.valueOf(article.charAt(index))) != null) {
                if (node.trie.get(String.valueOf(article.charAt(index))).isEnd == true) {
                    return true;
                }
                node = node.trie.get(String.valueOf(article.charAt(index)));
            } else {
                // 不匹配但是可以跳转
                if (node.jump != null) {
                    node = node.jump;
                    index--;
                } else { // 不匹配也不可跳转时从根节点匹配
                    // 根节点有匹配到的
                    if (root.trie.get(String.valueOf(article.charAt(index))) != null) {
                        node = root.trie.get(String.valueOf(article.charAt(index)));
                    }
                    // 根节点无匹配直接下一个
                }
            }

        }
        return false;
    }
}
